// CODMenu class plug-in for the MFC plug-in architecture
// Code copyright: R.I.Allen for plug-in stuff
// Most owner drawn menu code copyright Brent Corcum - modified by RA
// Some plug-in implementation of the CODMenu class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#include "ODMenu.h"
//#include <afxpriv.h>  //SK: makes A2W and other spiffy AFX macros work


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// static variables
#define BCMENU_GAP 1

#if _MFC_VER <0x400
#error This code does not work on Versions of MFC prior to 4.0
#endif

CFont CODMenu::m_menuFont;
CFont CODMenu::m_menuFontBold;
int CODMenu::m_iconX = 16;
int	CODMenu::m_iconY = 15;
std::map<int, int> CODMenu::m_commandToImage;
CImageList CODMenu::m_buttonImages;
CImageList CODMenu::m_disabledImages;
HINSTANCE CODMenu::m_hInstance;
HINSTANCE* CODMenu::m_hInstanceList;
int CODMenu::nPulgInCounts;
HMENU			CODMenu::m_menuBeingProcessed;
bool			CODMenu::m_bSysMenu;				// true if prcoessing a system menu
int				CODMenu::m_minSystemMenuWidth;	// min width of a system menu for correct drawing

enum Win32Type
{
	Win32s,
	WinNT3,
	Win95,
	Win98,
	WinME,
	WinNT4,
	Win2000,
	WinXP
};

extern Win32Type IsShellType();
static Win32Type g_Shell = IsShellType();


CODMenu::CODMenu()
{
	m_hInstance = NULL;
	m_bSysMenu = false;
	m_minSystemMenuWidth = 0;
}

CODMenu::CODMenu(bool special)
{
   UNREFERENCED_PARAMETER(special);

   // construct the menu font object used to measure all items
	LOGFONT m_lf;
	
	ZeroMemory((PVOID) &m_lf,sizeof(LOGFONT));
	
	NONCLIENTMETRICS nm;
	nm.cbSize = sizeof(NONCLIENTMETRICS);
	VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm, 0));
	// these fonts should auto destroy when the DLL unloads
	// create the normal menu item font
	m_lf = nm.lfMenuFont;
	m_menuFont.CreateFontIndirect(&m_lf);
	// create the default menu item font (bold)
	m_lf.lfWeight = FW_BOLD;
	m_menuFontBold.CreateFontIndirect(&m_lf);

	// image lists used, note the 500 max images!
	m_buttonImages.Create(m_iconX, m_iconY, ILC_COLOR32 | ILC_MASK, 1, 500);
	m_disabledImages.Create(m_iconX, m_iconY, ILC_COLOR32 | ILC_MASK, 1, 500);
}

CODMenu::~CODMenu()
{
	TRACE("CODMenu::~CODMenu()\n");
	if(m_hInstanceList)
		delete m_hInstanceList;
}


/////////////////////////////////////////////////////////////////////////////
// CODMenu message handlers

void CODMenu::EnumerateAndLoadToolbars()
{
	// This procedure is called by the InitialiseDLL function

	// When we intialise, we need to enumerate all the toolbar
	// resources in all the plug-in DLLs and the application
	// this allows us to generate a map of menu items which have toolbar
	// images available for them
	
	// First enumerate and use the appplications toolbar(s)
	

	if (m_hInstance)
	{
		TRACE("Enumerating application\n");
		EnumResourceNames(m_hInstance, RT_TOOLBAR,(ENUMRESNAMEPROC)EnumResNameProc, 0);
		
		// now enumerate all the plug-in DLL toolbars

		for(int dll = 0 ; dll < nPulgInCounts; dll++)
		{
			TRACE("Enumerating DLL %1d\n", dll);
			long * hinsts = (long *)m_hInstanceList;
			EnumResourceNames((HINSTANCE)(hinsts[dll]), RT_TOOLBAR,(ENUMRESNAMEPROC)EnumResNameProc, 0);
		}

	}

	// we now have all the toolbars loaded into the main image list m_buttonImages
	// generate the disabled versions of the images used
	CBitmap	disabledImage;
	CWindowDC dc(NULL);

	dc.SaveDC();
	disabledImage.CreateCompatibleBitmap(&dc, m_iconX, m_iconY);
	dc.SelectObject(&disabledImage);
	for(int image = 0 ; image < m_buttonImages.GetImageCount() ; image++)
	{
		CBitmap bmp;
		GetBitmapFromImageList(&dc, &m_buttonImages, image, bmp);
		DitherBlt3(&dc, bmp, ::GetSysColor(COLOR_3DFACE));
		m_disabledImages.Add(&bmp, ::GetSysColor(COLOR_3DFACE));
	}
	dc.RestoreDC(-1);
}

BOOL CALLBACK CODMenu::EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam)
{
    UNREFERENCED_PARAMETER(lParam);
	TRACE("Toolbar found, module %x, Type %1d, Name %1d\n", hModule, lpszType, lpszName);
	// There should be 2 resources,one of type RT_TOOLBAR, which enumerates the command IDs
	// the other of type RT_BITMAP, which are the images for each button

	// load in the RT_TOOLBAR button indexes
	HRSRC hrsrcToolbar = ::FindResource(hModule, lpszName, lpszType);
	HGLOBAL hToolbar = ::LoadResource(hModule, hrsrcToolbar);
	int size = ::SizeofResource(hModule, hrsrcToolbar);

	WORD* pToolbarData =(WORD*)::LockResource(hToolbar);
	// from examination of a toolbar resource, the layout it:
	// WORD : Version number(usually 1)
	// WORD : X_SIZE of image(16)
	// WORD : Y_SIZE of image(15)
	// WORD : NUMBER OF TOOLBAR BUTTONS
	// x * WORD : TOOLBAR BUTTON ID's
	// NOTE THAT A TOOLBAR BUTTON ID OF 0 IS A SEPARATOR
	if (pToolbarData[0] == 0x0001)
	{
		// we recognise this toolbar version, go ahead
		if (pToolbarData[1] == m_iconX && pToolbarData[2] == m_iconY)
		{
			// buttons are the correct size for a menu, lets load these images
			CBitmap	toolbarBitmap;
			// make sure we load the bitmap image from the correct module
			HINSTANCE old = AfxGetResourceHandle();
			AfxSetResourceHandle(hModule);
			toolbarBitmap.LoadBitmap(lpszName);
			AfxSetResourceHandle(old);

			// extract the IDs of each toolbar button
			for(int buttonIndex = 0 ; buttonIndex < pToolbarData[3] ; buttonIndex++)
			{

				if (pToolbarData[4 + buttonIndex] != 0)
				{
					// this is not a separator
					// make sure there is not already a map entry for this button
					if (m_commandToImage.find(pToolbarData[4 + buttonIndex]) == m_commandToImage.end())
					{
						// does not exist, add it
						m_commandToImage[pToolbarData[4 + buttonIndex]] = m_commandToImage.size();
					}
					else
					{
						TRACE("Warning, duplicate toolbar button %1d found, using first\n", 
								pToolbarData[4 + buttonIndex]);
					}
				}
			}
			BITMAP BMP;
			toolbarBitmap.GetBitmap(&BMP);
			// add the toolbar images on mass
			m_buttonImages.Add(&toolbarBitmap, ::GetSysColor(COLOR_3DFACE));
			toolbarBitmap.DeleteObject();
		}
	}
	// return TRUE to keep enumerting any other toolbar resources in the same module
	return TRUE;
}

void CODMenu::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
    UNREFERENCED_PARAMETER(nIndex);                                      
	if (TRUE)
	{
		TRACE("CODMenu::OnInitMenuPopup(CMenu* %0xd, UINT %d, BOOL %d)\n"
			,pPopupMenu,nIndex,bSysMenu);
		// iterate any menu about to be displayed and make sure
		// all the items have the ownerdrawn style set
		// We receive a WM_INITMENUPOPUP as each menu is displayed, even if the user
		// switches menus or brings up a sub menu. This means we only need to
		// set the style at the current popup level.
		// we also set the user item data to the index into the menu to allow
		// us to measure/draw the item correctly later
		//
		if (pPopupMenu != NULL)
		{
			m_bSysMenu = (bSysMenu != FALSE);
			m_menuBeingProcessed = pPopupMenu->m_hMenu;	// only valid for measure item calls
			int itemCount = pPopupMenu->GetMenuItemCount();
			for(int item = 0; item < itemCount; item++)
			{
				int itemID = pPopupMenu->GetMenuItemID(item);
				// make sure we do not change the state of the menu items as
				// we set the owner drawn style
				MENUITEMINFO	itemInfo;

				memset(&itemInfo, 0, sizeof(MENUITEMINFO));
				itemInfo.cbSize = sizeof(MENUITEMINFO);

				itemInfo.fMask = MIIM_STATE;
				pPopupMenu->GetMenuItemInfo(item, 
						&itemInfo, 
						TRUE);				// by position
				pPopupMenu->ModifyMenu(item, 
						itemInfo.fState | MF_BYPOSITION | MF_OWNERDRAW , 
						itemID,
						(LPCTSTR)item);
			//	BOOL bChecked = itemInfo.fState & ODS_CHECKED;
			}
		}
	}
}

void CODMenu::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
    UNREFERENCED_PARAMETER(nIDCtl);
	// check that the call is for an owner drawn menu
	if (lpMeasureItemStruct->CtlType == ODT_MENU)
	{
		MeasureItem(lpMeasureItemStruct);
	}
}

void CODMenu::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    UNREFERENCED_PARAMETER(nIDCtl);
	if (lpDrawItemStruct->CtlType == ODT_MENU)
	{
		DrawItem(lpDrawItemStruct);
	}
}

// FROM THIS POINT ONWARDS THE CODE IS A MODIFIED VERSION OF BRENT CORCUMS BCMENU CLASS

void CODMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
	USES_CONVERSION;
	MENUITEMINFO	itemInfo;
	CString			menuText;

	memset(&itemInfo, 0, sizeof(MENUITEMINFO));
	itemInfo.cbSize = sizeof(MENUITEMINFO);

	itemInfo.fMask = MIIM_STATE;
	::GetMenuItemInfo(m_menuBeingProcessed, lpMIS->itemData, TRUE, &itemInfo);

	UINT state = itemInfo.fState;
	
	int BCMENU_PAD = 4;
	if (lpMIS->itemID == 0)			// drawing a separator
	{
		lpMIS->itemWidth = 0;
		int temp = GetSystemMetrics(SM_CYMENU) >> 1;
		if (IsLunaMenuStyle())
			lpMIS->itemHeight = 3;
		else
			lpMIS->itemHeight = temp > (m_iconY + BCMENU_PAD) / 2 ? temp :(m_iconY + BCMENU_PAD) / 2;
	}
	else
	{
		// Obtain the width of the text:
		TCHAR	buffer[_MAX_PATH];
		CWnd *pWnd = AfxGetMainWnd();   // Get main window
		if (pWnd == NULL)
			pWnd = CWnd::GetDesktopWindow();
		CDC *pDC = pWnd->GetDC();    // Get device context
		CFont* pFont = NULL; // Select menu font in...

        // always measure using the bold version of the font
        //if (state & ODS_DEFAULT)
		pFont = pDC->SelectObject(&m_menuFontBold);
		//else
		//	pFont = pDC->SelectObject(&m_menuFont);// Select menu font in...

		::GetMenuString(m_menuBeingProcessed, lpMIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
  
		//Get pointer to text SK
		const wchar_t *lpstrText = A2W(buffer);
		 
		SIZE size;
		size.cx = 0;
		size.cy = 0;
		
		if (Win32s != g_Shell)
		{
			VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText, wcslen(lpstrText), &size)); //SK should also work on 95
			if (m_minSystemMenuWidth == 0)
			{
				SIZE minSize;
				const wchar_t *pMinText = L"Close     Alt + F4";
				// need to initialise
				::GetTextExtentPoint32W(pDC->m_hDC, pMinText, wcslen(pMinText), &minSize);
				if (IsLunaMenuStyle())
					m_minSystemMenuWidth = m_iconX + BCMENU_PAD + 8 + minSize.cx;
				else 
					m_minSystemMenuWidth = m_iconX + minSize.cx + m_iconX + BCMENU_GAP;
			}
		}
#ifndef UNICODE //can't be UNICODE for Win32s
		else
		{
			//it's Win32suckx
			RECT rect;
			rect.left = 0;
			rect.top = 0;
			size.cy = DrawText(pDC->m_hDC,
					(LPCTSTR)lpstrText, 
					wcslen(lpstrText), 
					&rect, 
					DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);
			//+3 makes at least three pixels space to the menu border
			size.cx = rect.right - rect.left + 3;
			size.cx += 3 * (size.cx / wcslen(lpstrText));
			if (m_minSystemMenuWidth == 0)
			{
				CRect minSize;
				const wchar_t *pMinText = L"Close     Alt + F4";
				DrawText(pDC->m_hDC,
						(LPCTSTR)pMinText, 
						wcslen(pMinText), 
						&minSize, 
						DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_CALCRECT);				// need to initialise
				if (IsLunaMenuStyle())
					m_minSystemMenuWidth = m_iconX + BCMENU_PAD + 8 + minSize.Width();
				else 
					m_minSystemMenuWidth = m_iconX + minSize.Width() + m_iconX + BCMENU_GAP;
			}
		}
#endif  
		
		CSize t = CSize(size);
		pDC->SelectObject(pFont); // Select old font in
		pWnd->ReleaseDC(pDC); // Release the DC

		// Set width and height:		
		if (IsLunaMenuStyle())
			lpMIS->itemWidth = m_iconX + BCMENU_PAD + 8 + t.cx;
		else 
			lpMIS->itemWidth = m_iconX + t.cx + m_iconX + BCMENU_GAP;
		int temp = GetSystemMetrics(SM_CYMENU);
		lpMIS->itemHeight = temp > m_iconY + BCMENU_PAD ? temp : m_iconY + BCMENU_PAD;
	}
	if (m_bSysMenu)
	{
		// solve problem with system menu items which we do not receive a WM_MEASUREITEM for
		if (lpMIS->itemWidth < m_minSystemMenuWidth)
		{
			// set to minimum width for correct draw
			lpMIS->itemWidth = m_minSystemMenuWidth;
		}
	}
}

void CODMenu::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	if (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
		DrawItem_Win9xNT2000(lpDIS);
	else
	{
		if (IsWinXPLuna())
		{
			DrawItem_WinXP(lpDIS);
		}
		else
		{
			DrawItem_Win9xNT2000(lpDIS);
		}	
	}
}


static CPINFO CPInfo;

Win32Type IsShellType()
{
	Win32Type ShellType;
	DWORD winVer;
	OSVERSIONINFO osvi;
	
	winVer=GetVersion();
	if (winVer<0x80000000)
	{/*NT */
		ShellType = WinNT3;
		memset(&osvi, 0, sizeof(OSVERSIONINFO));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&osvi);
		if (osvi.dwMajorVersion == 4L)
			ShellType = WinNT4;
		else if (osvi.dwMajorVersion == 5L && osvi.dwMinorVersion == 0L)
			ShellType = Win2000;
		else if (osvi.dwMajorVersion == 5L && osvi.dwMinorVersion == 1L)
			ShellType = WinXP;
	}
	else if (LOBYTE(LOWORD(winVer)) < 4)
		ShellType = Win32s;
	else
	{
		ShellType = Win95;
		memset(&osvi, 0, sizeof(OSVERSIONINFO));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&osvi);
		if (osvi.dwMajorVersion == 4L && osvi.dwMinorVersion == 10L)
			ShellType = Win98;
		else if (osvi.dwMajorVersion == 4L && osvi.dwMinorVersion == 90L)
			ShellType = WinME;
	}
	return ShellType;
}

BOOL CODMenu::IsLunaMenuStyle()
{
	if (IsWinXPLuna())
	{
		return TRUE;
	}
	return(FALSE);
}

BOOL CODMenu::IsNewShell()
{
	return(g_Shell >= Win95);
}

BOOL CODMenu::IsWinXPLuna()
{
	if (g_Shell == WinXP)
	{
		if (IsWindowsClassicTheme())
			return(FALSE);
		else
			return(TRUE);
	}
	return(FALSE);
}

BOOL CODMenu::IsWindowsClassicTheme()
{
	TCHAR Buf[_MAX_PATH+10];
	HKEY hKey;
	DWORD size;
	DWORD type; 
	long lRetCode; 
	static BOOL XPTheme_returnflag = FALSE;
	static BOOL XPTheme_checkflag = FALSE;
	
	if (XPTheme_checkflag)
		return(XPTheme_returnflag);

	XPTheme_checkflag = TRUE;
	lRetCode = RegOpenKeyEx(
			HKEY_CURRENT_USER, 
			_T("Software\\Microsoft\\Plus!\\Themes\\Current"), 
			0,
			KEY_READ,
			&hKey); 
	if (lRetCode == ERROR_SUCCESS)
	{ 
		size = _MAX_PATH;
		type = REG_SZ;
		lRetCode=::RegQueryValueEx(
			hKey,
			NULL,
			NULL,
			&type,
			(unsigned char *)Buf,
			&size);
		if (lRetCode == ERROR_SUCCESS)
		{
			TCHAR szClassicTheme[]=_T("Windows Classic.theme");
			int len = lstrlen(Buf);
			if (len >= lstrlen(szClassicTheme))
			{
				if (!lstrcmpi(&Buf[len - lstrlen(szClassicTheme)], szClassicTheme))
				{
					XPTheme_returnflag = TRUE;
				}
			}
		}
		RegCloseKey(hKey); 
	}
	return(XPTheme_returnflag);
}

void CODMenu::DrawItem_Win9xNT2000(LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);

	CDC*		pDC = CDC::FromHandle(lpDIS->hDC);
	CRect		rect;
	CBrush		brBackground;
	COLORREF	clrBack;
	UINT		state = lpDIS->itemState;
	MENUITEMINFO info;
	memset(&info, 0, sizeof(MENUITEMINFO));
	info.cbSize = sizeof(MENUITEMINFO);
	info.fMask = MIIM_CHECKMARKS;
	::GetMenuItemInfo((HMENU)lpDIS->hwndItem, lpDIS->itemID, MF_BYCOMMAND, &info);

	if (IsWinXPLuna())
		clrBack = GetSysColor(COLOR_3DFACE);
	else 
		clrBack = GetSysColor(COLOR_MENU);
	
	brBackground.CreateSolidBrush(clrBack);

	if (lpDIS->itemID == 0)			// drawing a separator
	{
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect(rect, &brBackground);
		rect.top += (rect.Height() >> 1);
		pDC->DrawEdge(&rect, EDGE_ETCHED, BF_TOP);
	}
	else
	{
		CRect	rect2;
		BOOL	standardflag = FALSE;
		BOOL	selectedflag = FALSE;
		BOOL	disableflag = FALSE;
		BOOL	checkflag = FALSE;
		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
		CBrush	m_brSelect;
		CPen	penBack;
		int		dy;
		int		nIconNormal = -1;
		
		// set some colors
		penBack.CreatePen(PS_SOLID, 0, clrBack);
		m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
		
		// draw the colored rectangle portion
		
		rect.CopyRect(&lpDIS->rcItem);
		rect2 = rect;
		
		// draw the up/down/focused/disabled state
		CString strText;
		TCHAR buffer[_MAX_PATH];
		::GetMenuString((HMENU)lpDIS->hwndItem, lpDIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
		strText = buffer;
		
		if (m_commandToImage.find(lpDIS->itemID) != m_commandToImage.end())
		{
			nIconNormal = m_commandToImage[lpDIS->itemID];
		}
		
		if (state & ODS_CHECKED && nIconNormal < 0)
		{
			if (state & ODS_SELECTED)
				checkflag = TRUE;
		}
		else if (nIconNormal != -1)
		{
			standardflag = TRUE;
			if (state & ODS_SELECTED && !(state & ODS_GRAYED))
				selectedflag = TRUE;
			else if (state & ODS_GRAYED) 
				disableflag = TRUE;
		}
		
		if (state & ODS_SELECTED)
		{
			// draw the down edges
			
			CPen *pOldPen = pDC->SelectObject(&penBack);
			
			// You need only Text highlight and thats what you get
			
			if (checkflag || standardflag || selectedflag || disableflag || state & ODS_CHECKED)
				rect2.SetRect(rect.left + m_iconX + 4 + BCMENU_GAP, rect.top, rect.right, rect.bottom);
			pDC->FillRect(rect2, &m_brSelect);
			
			pDC->SelectObject(pOldPen);
			crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
		}
		else 
		{
			CPen *pOldPen = pDC->SelectObject(&penBack);
			pDC->FillRect(rect, &brBackground);
			pDC->SelectObject(pOldPen);
			
			// draw the up edges	
			pDC->Draw3dRect(rect, clrBack, clrBack);
		}
		
		// draw the text if there is any
		//We have to paint the text only if the image is nonexistant
		
		dy =(rect.Height() - 4 - m_iconY) / 2;
		dy = dy < 0 ? 0 : dy;
		
		if (checkflag || standardflag || selectedflag || disableflag)
		{
			rect2.SetRect(rect.left + 1, rect.top + 1 + dy, rect.left + m_iconX + 3, rect.top + m_iconY + 3 + dy);
			pDC->Draw3dRect(rect2, clrBack, clrBack);
			if (checkflag)
			{
				pDC->FillRect(rect2, &brBackground);
				rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
				
				CPoint ptImage(rect.left + 2,rect.top + 2 + dy);
				
				rect2.SetRect(rect.left + 1, rect.top + 2 + dy, rect.left + m_iconX + 1, rect.top + m_iconY + 2 + dy);
				Draw3DCheckmark(pDC, rect2, state & ODS_SELECTED, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked);
			}
			else if (disableflag)
			{
				if (!selectedflag)
				{
					CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					pDC->Draw3dRect(rect2, clrBack, clrBack);
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else if (selectedflag)
			{
				pDC->FillRect(rect2, &brBackground);
				rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
				if (IsNewShell())
				{
					if (state & ODS_CHECKED)
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
					else
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW));
				}
				CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
				if (nIconNormal >= 0)
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
			}
			else
			{
				if (state & ODS_CHECKED)
				{
					CBrush brush;
					COLORREF col = clrBack;
					col = LightenColor(col, 0.6);
					brush.CreateSolidBrush(col);
					pDC->FillRect(rect2, &brush);
					brush.DeleteObject();
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					if (IsNewShell())
						pDC->Draw3dRect(rect2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
				}
				else
				{
					pDC->FillRect(rect2, &brBackground);
					rect2.SetRect(rect.left, rect.top + dy, rect.left + m_iconX + 4, rect.top + m_iconY + 4 + dy);
					pDC->Draw3dRect(rect2, clrBack, clrBack);
				}
				CPoint ptImage(rect.left + 2, rect.top + 2 + dy);
				if (nIconNormal >= 0)
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
			}
		}

		if (nIconNormal < 0 && state & ODS_CHECKED && !checkflag)
		{
			rect2.SetRect(rect.left + 1, rect.top + 2 + dy, rect.left + m_iconX + 1, rect.top + m_iconY + 2 + dy);
			if (state & ODS_CHECKED || info.hbmpUnchecked) 
			{
				Draw3DCheckmark(pDC, rect2, state & ODS_SELECTED, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked);
			}
		}
		
		//This is needed always so that we can have the space for check marks
		
		rect.left = rect.left + m_iconX + 8 + BCMENU_GAP; 
		
		if (!strText.IsEmpty())
		{			
			CFont *pFont;
			if (state & ODS_DEFAULT)
				pFont = pDC->SelectObject(&m_menuFontBold);
			else
				pFont = pDC->SelectObject(&m_menuFont);// Select menu font in...
			CRect rectt(rect.left, rect.top - 1, rect.right, rect.bottom - 1);
			
			// Find tabs
			
			CString leftStr;
			CString rightStr;

			int tablocr = strText.ReverseFind(_T('\t'));
			if (tablocr != -1)
			{
				rightStr = strText.Mid(tablocr + 1);
				leftStr = strText.Left(strText.Find(_T('\t')));
				rectt.right -= m_iconX;
			}
			else
				leftStr = strText;
			
			int iOldMode = pDC->GetBkMode();
			pDC->SetBkMode(TRANSPARENT);
			
			// Draw the text in the correct colour:
			
			UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
			UINT nFormatr = DT_RIGHT | DT_SINGLELINE | DT_VCENTER;
			if (!(state & ODS_GRAYED))
			{
				pDC->SetTextColor(crText);
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			else
			{				
				// Draw the disabled text
				if (!(state & ODS_SELECTED))
				{
					RECT offset = *rectt;
					offset.left += 1;
					offset.right += 1;
					offset.top += 1;
					offset.bottom += 1;
					pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
					pDC->DrawText(leftStr, &offset, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, &offset, nFormatr);
					pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
					pDC->DrawText(leftStr, rectt, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, rectt, nFormatr);
				}
				else
				{
					// And the standard Grey text:
					pDC->SetTextColor(clrBack);
					pDC->DrawText(leftStr, rectt, nFormat);
					if (tablocr != -1)
						pDC->DrawText(rightStr, rectt, nFormatr);
				}
			}
			pDC->SetBkMode(iOldMode);
			pDC->SelectObject(pFont);
		}
		
		penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	brBackground.DeleteObject();
}

void CODMenu::DrawItem_WinXP(LPDRAWITEMSTRUCT lpDIS)
{
	ASSERT(lpDIS != NULL);

	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
	CRect rect;
	CRect rect2;
	COLORREF newclrBack = GetSysColor(COLOR_3DFACE);
	COLORREF clrBack = GetSysColor(COLOR_WINDOW);
	UINT state = lpDIS->itemState;
	MENUITEMINFO info;
	memset(&info, 0, sizeof(MENUITEMINFO));
	info.cbSize = sizeof(MENUITEMINFO);
	info.fMask = MIIM_CHECKMARKS;
	::GetMenuItemInfo((HMENU)lpDIS->hwndItem, lpDIS->itemID, MF_BYCOMMAND, &info);

	clrBack = DarkenColor(clrBack, 0.02);
	CFont *pFont = NULL;
	if (!IsWinXPLuna())
		newclrBack = LightenColor(newclrBack, 0.25);
	CBrush newbrBackground;
	CBrush brBackground;
	
	brBackground.CreateSolidBrush(clrBack);
	newbrBackground.CreateSolidBrush(newclrBack);
	int BCMENU_PAD = 4;
	int barwidth = m_iconX + BCMENU_PAD;
	
	if (lpDIS->itemID == 0)			// drawing a separator
	{
		rect.CopyRect(&lpDIS->rcItem);
		pDC->FillRect(rect, &brBackground);
		rect2.SetRect(rect.left, rect.top, rect.left + barwidth, rect.bottom);
		rect.top += rect.Height() >> 1;
		rect.left = rect2.right + BCMENU_PAD;
		pDC->DrawEdge(&rect, EDGE_ETCHED, BF_TOP);
		pDC->FillRect(rect2, &newbrBackground);
		pDC->Draw3dRect(rect2, newclrBack, newclrBack);
	}
	else
	{
		BOOL standardflag = FALSE;
		BOOL selectedflag = FALSE;
		BOOL disableflag = FALSE;
		BOOL checkflag = FALSE;
		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
		COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
		COLORREF crSelectFill;
		if (!IsWinXPLuna())
			crSelectFill = LightenColor(crSelect, 0.85);
		else
			crSelectFill = LightenColor(crSelect, 0.7);
		CBrush m_brSelect;
		CPen penBack;
		int dx;
		int dy;
		int nIconNormal = -1;
		
		// set some colors
		penBack.CreatePen(PS_SOLID, 0, clrBack);
		m_brSelect.CreateSolidBrush(crSelectFill);
		
		// draw the colored rectangle portion
		
		rect.CopyRect(&lpDIS->rcItem);
		rect2 = rect;
		
		// draw the up/down/focused/disabled state
		
		CString strText;
		TCHAR buffer[_MAX_PATH];
		::GetMenuString((HMENU)lpDIS->hwndItem, lpDIS->itemData, buffer, _MAX_PATH, MF_BYPOSITION);
		strText = buffer;
		
		if (m_commandToImage.find(lpDIS->itemID) != m_commandToImage.end())
		{
			nIconNormal = m_commandToImage[lpDIS->itemID];
		}

		if (state & ODS_CHECKED && nIconNormal < 0)
		{
			if (state & ODS_SELECTED)
				checkflag = TRUE;
		}
		else if (nIconNormal != -1)
		{
			standardflag = TRUE;
			if (state & ODS_SELECTED && !(state & ODS_GRAYED))
				selectedflag = TRUE;
			else if (state & ODS_GRAYED)
				disableflag = TRUE;
		}
		
		if (state & ODS_SELECTED)
		{
			// draw the down edges			
			CPen *pOldPen = pDC->SelectObject(&penBack);
			
			pDC->FillRect(rect, &m_brSelect);
			pDC->Draw3dRect(rect, crSelect, crSelect);
			
			pDC->SelectObject(pOldPen);
		}
		else 
		{
			rect2.SetRect(rect.left, rect.top, rect.left + barwidth, rect.bottom);
			CPen *pOldPen = pDC->SelectObject(&penBack);
			pDC->FillRect(rect, &brBackground);
			pDC->FillRect(rect2, &newbrBackground);
			pDC->SelectObject(pOldPen);
			
			// draw the up edges			
			pDC->Draw3dRect(rect, clrBack, clrBack);
			pDC->Draw3dRect(rect2, newclrBack, newclrBack);
		}
		
		// draw the text if there is any
		//We have to paint the text only if the image is nonexistant
		
		dy =(int)(0.5 + (rect.Height() - m_iconY) / 2.0);
		dy = dy < 0 ? 0 : dy;
		dx =(int)(0.5 + (barwidth - m_iconX) / 2.0);
		dx = dx < 0 ? 0 : dx;
		rect2.SetRect(rect.left + 1, rect.top + 1, rect.left + barwidth - 2, rect.bottom - 1);
		
		if (checkflag || standardflag || selectedflag || disableflag)
		{
			if (checkflag)
			{
				pDC->FillRect(rect2, &newbrBackground);
				CPoint ptImage(rect.left + dx, rect.top + dy);		
				if (state & ODS_SELECTED)
    				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
				else
    				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
			}
			else if (disableflag)
			{
				CPoint ptImage(rect.left + dx, rect.top + dy);
				if (!selectedflag)
				{
					COLORREF transparentcol = newclrBack;
					if (state & ODS_SELECTED)
						transparentcol = crSelectFill;
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
					if (state & ODS_SELECTED)
						pDC->Draw3dRect(rect, crSelect, crSelect);
				}
				else
				{
					if (nIconNormal >= 0)
						m_disabledImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else if (selectedflag)
			{
				CPoint ptImage(rect.left + dx, rect.top + dy);
				if (state & ODS_CHECKED)
				{
					CBrush brushin;
					brushin.CreateSolidBrush(LightenColor(crSelect, 0.55));
					pDC->FillRect(rect2, &brushin);
					brushin.DeleteObject();
					pDC->Draw3dRect(rect2, crSelect, crSelect);
					ptImage.x -= 1;
					ptImage.y -= 1;
				}
				else
					pDC->FillRect(rect2, &m_brSelect);
				if (nIconNormal >= 0)
				{
					m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
			}
			else
			{
				if (state & ODS_CHECKED)
				{
					CBrush brushin;
					brushin.CreateSolidBrush(LightenColor(crSelect, 0.85));
					pDC->FillRect(rect2, &brushin);
					brushin.DeleteObject();
					pDC->Draw3dRect(rect2, crSelect, crSelect);
					CPoint ptImage(rect.left + dx - 1, rect.top + dy - 1);
					if (nIconNormal)
						m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
				}
				else
				{
					pDC->FillRect(rect2, &newbrBackground);
					pDC->Draw3dRect(rect2, newclrBack, newclrBack);
					CPoint ptImage(rect.left + dx, rect.top + dy);
					if (nIconNormal >= 0)
					{
						m_buttonImages.Draw(pDC, nIconNormal, ptImage, ILD_TRANSPARENT);
					}
				}
			}
		}
		if (nIconNormal < 0 && state & ODS_CHECKED && !checkflag)
		{
			if (state & ODS_CHECKED || info.hbmpUnchecked) 
			{
				DrawXPCheckmark(pDC, rect2, state & ODS_CHECKED ? info.hbmpChecked : info.hbmpUnchecked, crSelect, state&ODS_SELECTED);
			}
		}
		
		// This is needed always so that we can have the space for check marks
		rect.left = rect.left + barwidth + 8; 
		
		if (!strText.IsEmpty())
		{			
			CRect rectt(rect.left, rect.top - 1, rect.right, rect.bottom - 1);
			
			// Find tabs			
			CString leftStr;
			CString rightStr;
			int tablocr = strText.ReverseFind(_T('\t'));
			if (tablocr != -1)
			{
				rightStr = strText.Mid(tablocr + 1);
				leftStr = strText.Left(strText.Find(_T('\t')));
				rectt.right -= m_iconX;
			}
			else
				leftStr = strText;
			
			int iOldMode = pDC->GetBkMode();
			pDC->SetBkMode(TRANSPARENT);
			
			// Draw the text in the correct colour:
			
			UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
			UINT nFormatr = DT_RIGHT | DT_SINGLELINE | DT_VCENTER;
			if (!(state & ODS_GRAYED))
			{
				pDC->SetTextColor(crText);
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			else
			{
				RECT offset = *rectt;
				offset.left += 1;
				offset.right += 1;
				offset.top += 1;
				offset.bottom += 1;
				if (!IsWinXPLuna())
				{
					COLORREF graycol = GetSysColor(COLOR_GRAYTEXT);
					if (!(state & ODS_SELECTED))
						graycol = LightenColor(graycol, 0.4);
					pDC->SetTextColor(graycol);
				}
				else 
					pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
				pDC->DrawText(leftStr, rectt, nFormat);
				if (tablocr != -1)
					pDC->DrawText(rightStr, rectt, nFormatr);
			}
			pDC->SetBkMode(iOldMode);
		}
		
		penBack.DeleteObject();
		m_brSelect.DeleteObject();
	}
	brBackground.DeleteObject();
	newbrBackground.DeleteObject();
}

BOOL CODMenu::GetBitmapFromImageList( CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp )
{
	HICON hIcon = imglist->ExtractIcon(nIndex);
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	bmp.CreateCompatibleBitmap(pDC, m_iconX, m_iconY);

	CBitmap* pOldBmp = dc.SelectObject(&bmp);
	CBrush brush;
	COLORREF newclrBack;
	newclrBack = GetSysColor(COLOR_3DFACE);
	brush.CreateSolidBrush(newclrBack);
	::DrawIconEx(
		dc.GetSafeHdc(), 
		0,
		0,
		hIcon,
		m_iconX,
		m_iconY,
		0,
		(HBRUSH)brush,
		DI_NORMAL
		);
	dc.SelectObject(pOldBmp);
	dc.DeleteDC();
	// the icon is not longer needed
	::DestroyIcon(hIcon);
	return(TRUE);
}

void CODMenu::DitherBlt3(CDC *drawdc, CBitmap &bmp, COLORREF bgcolor)
{
	GetDisabledBitmap(bmp,bgcolor);
	CDC dc;
	dc.CreateCompatibleDC(NULL);
	CBitmap *pdcOldBmp = dc.SelectObject(&bmp);
	drawdc->BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	// reset DCs
	dc.SelectObject(pdcOldBmp);
	dc.DeleteDC();
}

void CODMenu::DitherBlt2(CDC *drawdc, CBitmap &bmp, COLORREF bgcolor)
{
	// create a monochrome memory DC
	CDC ddc;
	ddc.CreateCompatibleDC(NULL);
	CBitmap bwbmp;
	bwbmp.CreateCompatibleBitmap(&ddc, m_iconX, m_iconY);
	CBitmap *pddcOldBmp = ddc.SelectObject(&bwbmp);
	
	CDC dc;
	dc.CreateCompatibleDC(NULL);
	CBitmap *pdcOldBmp = dc.SelectObject(&bmp);
	
	// build a mask
	ddc.PatBlt(0, 0, m_iconX, m_iconY, WHITENESS);
	dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
	ddc.BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
	ddc.BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCPAINT);
	
	// Copy the image from the toolbar into the memory DC
	// and draw it(grayed) back into the toolbar.
	dc.FillSolidRect(0,0, m_iconX, m_iconY, bgcolor);
	//SK: Looks better on the old shell
	dc.SetBkColor(RGB(0, 0, 0));
	dc.SetTextColor(RGB(255, 255, 255));
	CBrush brShadow;
	CBrush brHilight;
	brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
	brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
	CBrush *pOldBrush = dc.SelectObject(&brHilight);
	dc.BitBlt(0, 0, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(1, 1, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	dc.BitBlt(1, 1, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	dc.SelectObject(&brShadow);
	dc.BitBlt(0, 0, m_iconX, m_iconY, &ddc, 0, 0, 0x00E20746L);
	drawdc->BitBlt(0, 0, m_iconX, m_iconY, &dc, 0, 0, SRCCOPY);
	// reset DCs
	ddc.SelectObject(pddcOldBmp);
	ddc.DeleteDC();
	dc.SelectObject(pOldBrush);
	dc.SelectObject(pdcOldBmp);
	dc.DeleteDC();
	
	brShadow.DeleteObject();
	brHilight.DeleteObject();
	bwbmp.DeleteObject();
}

COLORREF CODMenu::LightenColor(COLORREF col, double factor)
{
	if (factor > 0.0 && factor <= 1.0)
	{
		BYTE red = GetRValue(col);
		BYTE green = GetGValue(col);
		BYTE blue = GetBValue(col);
		BYTE lightred = (BYTE)((factor * (255 - red)) + red);
		BYTE lightgreen = (BYTE)((factor * (255 - green)) + green);
		BYTE lightblue = (BYTE)((factor * (255 - blue)) + blue);
		col = RGB(lightred, lightgreen, lightblue);
	}
	return(col);
}

COLORREF CODMenu::DarkenColor(COLORREF col, double factor)
{
	if (factor > 0.0 && factor <= 1.0)
	{
		BYTE red = GetRValue(col);
		BYTE green = GetGValue(col);
		BYTE blue = GetBValue(col);
		BYTE lightred =(BYTE)(red - (factor * red));
		BYTE lightgreen =(BYTE)(green - (factor * green));
		BYTE lightblue =(BYTE)(blue - (factor * blue));
		col = RGB(lightred, lightgreen, lightblue);
	}
	return(col);
}

BOOL CODMenu::Draw3DCheckmark(CDC *dc, const CRect& rc, BOOL bSelected, HBITMAP hbmCheck)
{
	CRect rcDest = rc;
	CBrush brush;
	COLORREF col;
	if (IsWinXPLuna())
		col = GetSysColor(COLOR_3DFACE);
	else 
		col = GetSysColor(COLOR_MENU);
	if (!bSelected)
		col = LightenColor(col, 0.6);
	brush.CreateSolidBrush(col);
	dc->FillRect(rcDest,&brush);
	brush.DeleteObject();
	if (IsNewShell()) //SK: looks better on the old shell
		dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
	if (!hbmCheck)
		DrawCheckMark(dc, rc.left + 4, rc.top + 4, GetSysColor(COLOR_MENUTEXT));
	else 
		DrawRadioDot(dc, rc.left + 5, rc.top + 4, GetSysColor(COLOR_MENUTEXT));
	return TRUE;
}

BOOL CODMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck, COLORREF &colorout, BOOL selected)
{
	CBrush brushin;
	COLORREF col;
	int dx;
	int dy;
	dy = (rc.Height() >> 1) - 3;
	dy = dy < 0 ? 0 : dy;
	dx = (rc.Width() >> 1) - 3;
	dx = dx < 0 ? 0 : dx;

	if (selected)
		col = LightenColor(colorout, 0.55);
	else
		col = LightenColor(colorout, 0.85);
	brushin.CreateSolidBrush(col);
	dc->FillRect(rc, &brushin);
	brushin.DeleteObject();
	dc->Draw3dRect(rc, colorout, colorout);

	if (!hbmCheck)
		DrawCheckMark(dc, rc.left + dx, rc.top + dy, GetSysColor(COLOR_MENUTEXT), TRUE);
	else
		DrawRadioDot(dc, rc.left + dx, rc.top + dy, GetSysColor(COLOR_MENUTEXT));
	return TRUE;
}

void CODMenu::GetDisabledBitmap(CBitmap &bmp,COLORREF background)
{
	CDC ddc;
	COLORREF bgcol,col,discol;
	BITMAP BitMap;

	bmp.GetBitmap(&BitMap);
	ddc.CreateCompatibleDC(NULL);
	CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);

	// use this to get the background color, takes into account color shifting
	CDC ddc2;
	CBrush brush;
	CBitmap bmp2;
	ddc2.CreateCompatibleDC(NULL);
	bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
	col=GetSysColor(COLOR_3DFACE);
	brush.CreateSolidBrush(col);
	CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
	CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
	ddc2.FillRect(rect,&brush);
	bgcol=ddc2.GetPixel(1,1);
	brush.DeleteObject();
	ddc2.SelectObject(pddcOldBmp2);
	discol=GetSysColor(COLOR_BTNSHADOW);

	for (int i = 0; i < BitMap.bmWidth; ++i)
	{
		for (int j = 0; j <BitMap.bmHeight ; ++j)
		{
			col=ddc.GetPixel(i,j);
			if (col != bgcol)
			{
				BYTE r = GetRValue(col);
				BYTE g = GetGValue(col);
				BYTE b = GetBValue(col);
				int avgcol = (r + g + b) / 3;
				double factor = avgcol / 255.0;
				ddc.SetPixel(i, j, LightenColor(discol,factor));
			}
			else
			{
				if (background)
					ddc.SetPixel(i, j, background);
			}
		}
	}
	ddc.SelectObject(pddcOldBmp);
}

void CODMenu::DrawRadioDot(CDC *pDC, int x, int y, COLORREF color)
{
	CRect rcDot(x, y, x + 6, y + 6);
	CBrush brush;
	CPen pen;
	brush.CreateSolidBrush(color);
	pen.CreatePen(PS_SOLID, 0, color);
	CBrush *pOldBrush = pDC->SelectObject(&brush);
	CPen *pOldPen = pDC->SelectObject(&pen);
	pDC->Ellipse(&rcDot);
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
	pen.DeleteObject();
	brush.DeleteObject();
}

void CODMenu::DrawCheckMark(CDC* pDC, int x, int y, COLORREF color, BOOL narrowflag)
{
	int dp = 0;
	CPen penBack;
	penBack.CreatePen(PS_SOLID, 0, color);
	CPen *pOldPen = pDC->SelectObject(&penBack);
	if (narrowflag)
		dp = 1;

	pDC->MoveTo(x, y + 2);
	pDC->LineTo(x, y + 5 - dp);
	
	pDC->MoveTo(x + 1, y + 3);
	pDC->LineTo(x + 1, y + 6 - dp);
	
	pDC->MoveTo(x + 2, y + 4);
	pDC->LineTo(x + 2, y + 7 - dp);
	
	pDC->MoveTo(x + 3, y + 3);
	pDC->LineTo(x + 3, y + 6 - dp);
	
	pDC->MoveTo(x + 4, y + 2);
	pDC->LineTo(x + 4, y + 5 - dp);
	
	pDC->MoveTo(x + 5, y + 1);
	pDC->LineTo(x + 5, y + 4 - dp);
	
	pDC->MoveTo(x + 6, y);
	pDC->LineTo(x + 6, y + 3 - dp);
	
	pDC->SelectObject(pOldPen);
	penBack.DeleteObject();
}

